/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.logging;

import org.zhiqim.kernel.util.Strings;

/**
 * 日志类，由日志工厂创建
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
public class Log implements LogConstants
{
    private final String logName;
    private final Class<?> logClass;
    
    private LogService logService;
    
    /***********************************************************************/
    //定义日志类由日志工厂类（LogFactory）创建
    /***********************************************************************/
    
    Log(String logName, LogService logService)
    {
        this.logName = logName;
        this.logClass = null;
        this.logService = logService;
    }
    
    Log(Class<?> logClass, LogService logService)
    {
        this.logName = null;
        this.logClass = logClass;
        this.logService = logService;
    }
    
    /** 支持切换日志服务 */
    void setLogService(LogService logService)
    {
        this.logService = logService;
    }
    
    /***********************************************************************/
    //调试
    /***********************************************************************/
 
    public void debug(Object message)
    {
        append(DEBUG, message, null);
    }
    
    public void debug(Throwable throwable)
    {
        append(DEBUG, null, throwable);
    }
    
    public void debug(Object message, Object... arguments)
    {
        append(DEBUG, message, null, LogFormat.STRING, arguments);
    }
    
    public void debug(Object message, Throwable throwable, Object... arguments)
    {
        append(DEBUG, message, throwable, LogFormat.STRING, arguments);
    }
    
    public void debug(Object message, LogFormat format, Object... arguments)
    {
        append(DEBUG, message, null, format, arguments);
    }
    
    public void debug(Object message, Throwable throwable, LogFormat format, Object... arguments)
    {
        append(DEBUG, message, throwable, format, arguments);
    }
    
    /***********************************************************************/
    //信息
    /***********************************************************************/
    
    public void info(Object message)
    {
        append(INFO, message, null);
    }
    
    public void info(Throwable throwable)
    {
        append(INFO, null, throwable);
    }
    
    public void info(Object message, Object... arguments)
    {
        append(INFO, message, null, LogFormat.STRING, arguments);
    }
    
    public void info(Object message, Throwable throwable, Object... arguments)
    {
        append(INFO, message, throwable, LogFormat.STRING, arguments);
    }
    
    public void info(Object message, LogFormat format, Object... arguments)
    {
        append(INFO, message, null, format, arguments);
    }
    
    public void info(Object message, Throwable throwable, LogFormat format, Object... arguments)
    {
        append(INFO, message, throwable, format, arguments);
    }
    
    /***********************************************************************/
    //错误
    /***********************************************************************/
    
    public void error(Object message)
    {
        append(ERROR, message, null);
    }
    
    public void error(Throwable throwable)
    {
        append(ERROR, null, throwable);
    }
    
    public void error(Object message, Object... arguments)
    {
        append(ERROR, message, null, LogFormat.STRING, arguments);
    }
    
    public void error(Object message, Throwable throwable, Object... arguments)
    {
        append(ERROR, message, throwable, LogFormat.STRING, arguments);
    }
    
    public void error(Object message, LogFormat format, Object... arguments)
    {
        append(ERROR, message, null, format, arguments);
    }
    
    public void error(Object message, Throwable throwable, LogFormat format, Object... arguments)
    {
        append(ERROR, message, throwable, format, arguments);
    }
    
    /***********************************************************************/
    //后端警告
    /***********************************************************************/
    
    public void warn(Object message)
    {
        append(WARN, message, null);
    }
    
    public void warn(Throwable throwable)
    {
        append(WARN, null, throwable);
    }
    
    public void warn(Object message, Object... arguments)
    {
        append(WARN, message, null, LogFormat.STRING, arguments);
    }
    
    public void warn(Object message, Throwable throwable, Object... arguments)
    {
        append(WARN, message, throwable, LogFormat.STRING, arguments);
    }
    
    public void warn(Object message, LogFormat format, Object... arguments)
    {
        append(WARN, message, null, format, arguments);
    }
    
    public void warn(Object message, Throwable throwable, LogFormat format, Object... arguments)
    {
        append(WARN, message, throwable, format, arguments);
    }
    
    /***********************************************************************/
    //后台危急错误
    /***********************************************************************/
    
    public void fatal(Object message)
    {
        append(FATAL, message, null);
    }
    
    public void fatal(Throwable throwable)
    {
        append(FATAL, null, throwable);
    }
    
    public void fatal(Object message, Object... arguments)
    {
        append(FATAL, message, null, LogFormat.STRING, arguments);
    }
    
    public void fatal(Object message, Throwable throwable, Object... arguments)
    {
        append(FATAL, message, throwable, LogFormat.STRING, arguments);
    }
    
    public void fatal(Object message, LogFormat format, Object... arguments)
    {
        append(FATAL, message, null, format, arguments);
    }
    
    public void fatal(Object message, Throwable throwable, LogFormat format, Object... arguments)
    {
        append(FATAL, message, throwable, format, arguments);
    }
    
    /***********************************************************************/
    //判断是否开启
    /***********************************************************************/
    
    /** 调试是否开启 */
    public boolean isDebugEnabled()
    {
        return isEnabled(DEBUG);
    }

    /** 信息是否开启 */
    public boolean isInfoEnabled()
    {
        return isEnabled(INFO);
    }

    /** 错误是否开启 */
    public boolean isErrorEnabled()
    {
        return isEnabled(ERROR);
    }
    
    /** 后端警告是否开启 */
    public boolean isWarnEnabled()
    {
        return isEnabled(WARN);
    }

    /** 后端危急错误是否开启 */
    public boolean isFatalEnabled()
    {
        return isEnabled(FATAL);
    }
    
    /**
     * 写入日志，支持异常日志，异常对象为null表示无异常
     * 
     * @param level         日志级别
     * @param message       日志信息
     * @param throwable     异常对象
     */
    private void append(int level, Object message, Throwable throwable)
    {
        Logger logger = logService.getLogger(this, level);
        if (logger == null || !logger.isEnabled(this, level))
        {//未开启
            return;
        }
        
        logger.append(this, level, String.valueOf(message), throwable);
    }
    
    /**
     * 写入日志，支持异常日志
     * 
     * @param level         日志级别
     * @param message       日志信息
     * @param throwable     日志异常
     * @param format        格式化信息类型
     * @param arguments     格式化信息参数
     */
    private void append(int level, Object message, Throwable throwable, LogFormat format, Object... arguments)
    {
        Logger logger = logService.getLogger(this, level);
        if (logger == null || !logger.isEnabled(this, level))
        {//未开启
            return;
        }
        
        String msg = String.valueOf(message);
        if (arguments == null || arguments.length == 0)
        {//没有格式化参数
            logger.append(this, level, msg, throwable);
            return;
        }
        
        if (format == LogFormat.STRING || format == LogFormat.BOTH)
        {//支持格式化字符串
            msg = Strings.format(msg, arguments);
        }
        
        if (format == LogFormat.MESSAGE || format == LogFormat.BOTH)
        {//支持格式化信息
            msg = Strings.formatMessage(msg, arguments);
        }
        
        logger.append(this, level, msg, throwable);
    }
    
    /**
     * 判断日志级别是否开启
     * 
     * @param level     日志级别
     * @return          =true表示开启,=false表示未开启
     */
    private boolean isEnabled(int level)
    {
        return logService.isEnabled(this, level);
    }
    
    /***********************************************************************/
    //获取属性
    /***********************************************************************/
    
    public String getLogName()
    {
        return logName;
    }

    public Class<?> getLogClass()
    {
        return logClass;
    }
    
    public LogService getLogService()
    {
        return logService;
    }
    
    /** 获取日志生成时对应的参数名 */
    public String getLogNameOrClassName()
    {
        return (logClass != null)?logClass.getName():logName;
    }
}
